package org.yixiu.activiti.util;

import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.BpmnAutoLayout;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.*;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

@Slf4j
public class BpmnModelUtil {

    public static void generateBPMNModel(Map<String,String> props, SortedMap<String,String> taskMap){

        String processId = props.get("processId");
        if(StringUtils.isBlank(processId)){
            return;
        }

        BpmnModel model = new BpmnModel();
        final Process process = new Process();
        process.setId(processId);
        model.addProcess(process);

        Map<String,String> flows = new HashMap<>();
        final List<String> flowNames = new LinkedList<>();
        process.addFlowElement(createStartEvent());
        taskMap.forEach((id, name) -> {
            flowNames.add(id);
            process.addFlowElement(createServiceTask(id,name));
        });
        process.addFlowElement(createEndEvent());

        String prev = "start";
        for (String flowName : flowNames) {
            flows.put(prev,flowName);
            prev = flowName;
        }
        flows.put(prev,"end");

        flows.forEach((source, to) -> {
            process.addFlowElement(createSequenceFlow(source,to));
        });

        new BpmnAutoLayout(model).execute();

        BpmnXMLConverter converter = new BpmnXMLConverter();
        byte[] convertToXML = converter.convertToXML(model);
        String xmlStr = new String(convertToXML);
        xmlStr = xmlStr.replaceAll("&lt;","<").replaceAll("&gt;",">");
        System.out.println(xmlStr);
    }

    private static ServiceTask createServiceTask(String id,String name){
        ServiceTask serviceTask = new ServiceTask();
        if(StringUtils.isNotBlank(id))
            serviceTask.setId(id);
        if(StringUtils.isNotBlank(name))
            serviceTask.setName(name);

        return serviceTask;
    }

    private static SequenceFlow createSequenceFlow(String from,String to){
        SequenceFlow flow = new SequenceFlow();
        flow.setSourceRef(from);
        flow.setTargetRef(to);
        return flow;
    }

    private static StartEvent createStartEvent(){
        StartEvent startEvent = new StartEvent();
        startEvent.setId("start");
        return startEvent;
    }

    private static EndEvent createEndEvent(){
        EndEvent endEvent = new EndEvent();
        endEvent.setId("end");
        return endEvent;
    }
}
